import createElement from './createElement.js';
import patchVnode from './patchVnode.js';

function isSameVnode(oldVnode, newVnode) {
  return oldVnode.tag === newVnode.tag && oldVnode.key === newVnode.key;
}

export default function updateChildren(parentElm, oldChildren, newChildren) {
  console.log('updateChildren');

  let oldStartIdx = 0;
  let newStartIdx = 0;
  let oldEndIdx = oldChildren.length - 1;
  let newEndIdx = newChildren.length - 1;

  let oldStartVnode = oldChildren[0];
  let oldEndVnode = oldChildren[oldEndIdx];

  let newStartVnode = newChildren[0];
  let newEndVnode = newChildren[newEndIdx];

  let keyMap = null;

  while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
    if (oldStartVnode === undefined) {
      oldStartVnode = oldChildren[++oldStartIdx];
    } else if (oldEndVnode === undefined) {
      oldEndVnode = oldChildren[--oldEndIdx];
    } else if (isSameVnode(oldStartVnode, newStartVnode)) {
      console.log('新前 旧前比较');
      patchVnode(oldStartVnode, newStartVnode);
      // 打完补丁，移动指针
      oldStartIdx++;
      newStartIdx++;
      oldStartVnode = oldChildren[oldStartIdx];
      newStartVnode = newChildren[newStartIdx];
    } else if (isSameVnode(oldEndVnode, newEndVnode)) {
      console.log('新后 旧后比较');
      patchVnode(oldEndVnode, newEndVnode);
      // 打完补丁，移动指针
      oldEndIdx--;
      newEndIdx--;
      oldEndVnode = oldChildren[oldEndIdx];
      newEndVnode = newChildren[newEndIdx];
    } else if (isSameVnode(oldStartVnode, newEndVnode)) {
      console.log('新后 旧前比较,粗略的可以理解元素被移动到了后面');
      patchVnode(oldStartVnode, newEndVnode);
      // 节点添加或移除了正确的属性后，要被移动到正确的位置
      parentElm.insertBefore(oldStartVnode.elm, oldEndVnode.elm.nextSibling);
      // 打完补丁，移动指针
      oldStartIdx++;
      newEndIdx--;
      oldStartVnode = oldChildren[oldStartIdx];
      newEndVnode = newChildren[newEndIdx];
    } else if (isSameVnode(oldEndVnode, newStartVnode)) {
      console.log('新前 旧后比较，元素被移动到前面');
      patchVnode(oldEndVnode, newStartVnode);
      // 节点添加或移除了正确的属性后，要被移动到正确的位置
      parentElm.insertBefore(oldEndVnode.elm, oldStartVnode.elm);

      oldEndIdx--;
      newStartIdx++;
      oldEndVnode = oldChildren[oldEndIdx];
      newStartVnode = newChildren[newStartIdx];
    } else {
      console.log('未命中，需要遍历旧节点找目标节点');
      if (!keyMap) {
        keyMap = new Map();
        // 把oldStartIdx newEndIdx之间的元素放到映射表中
        for (let i = oldStartIdx; i <= newEndIdx; i++) {
          keyMap.set(oldChildren[i].key, i);
        }
      }

      const aimIdx = keyMap.get(newStartVnode.key);
      if (aimIdx) {
        // 存在 就 打补丁 移动到正确的位置
        const aimOldVnode = oldChildren[aimIdx];
        patchVnode(aimOldVnode, newStartVnode);

        // 元素已经处理，指针再移动到这就跳过，修改oldChildren数组对应元素
        oldChildren[aimIdx] = undefined;

        parentElm.insertBefore(aimOldVnode.elm, oldStartVnode.elm);
      } else {
        // 不存在 重新创建 插入到正确的位置
        parentElm.insertBefore(createElement(newStartVnode), oldStartVnode.elm);
      }

      // 以上处理完成newStartVnode
      // 匹配到旧节点，将它从oldChildren中移除，避免二次操作
      // 没有匹配到旧节点，创建新的，并不修改旧指针的指向
      newStartVnode = newChildren[++newStartIdx];
    }
  }

  // 说明还有新元素要添加
  if (newStartIdx <= newEndIdx) {
    for (let i = newStartIdx; i <= newEndIdx; i++) {
      parentElm.insertBefore(createElement(newChildren[i]), oldChildren[oldStartIdx].elm);
    }
  }
  // 说明右旧元素要被删除
  if (oldStartIdx <= oldEndIdx) {
    for (let i = oldStartIdx; i <= oldEndIdx; i++) {
      if (oldChildren[i]) {
        parentElm.removeChild(oldChildren[i].elm);
      }
    }
  }
}
